#include "headers/ifileapp.hpp"
#include "headers/ifile_server_comms.hpp"
#include "headers/ifile_settings_dialog.hpp"

#include <QDebug>
#include <QFileDialog>
#include <QMessageBox>
#include <QTableWidgetItem>

//----------------------------------------------------------------------------------------

ifileApp::ifileApp(QWidget * parent)
    : QMainWindow(parent)
{
	ui.setupUi(this);

    ifileServerComms = NULL;
    uploadProcess = NULL;
    uploadTableItemOne = NULL;
    uploadTableItemTwo = NULL;
    uploadTableItemThree = NULL;
    uploadTableItemFour = NULL;
    folderTableItemOne = NULL;
    folderTableItemTwo = NULL;
    folderTableItemThree = NULL;
    folderTableItemFour = NULL;
    folderTableItemFive = NULL;
    folderTableItemSix = NULL;
    fileTableItemTwo = NULL;
    fileTableItemThree = NULL;
    fileTableItemFour = NULL;
    fileTableItemFive = NULL;
    fileTableItemSix = NULL;
    fileTableItemSeven = NULL;
    accountFolders = NULL;
    groupCheckBox = NULL;
    signalMapper = NULL;

    maxUploadSlots = 1;
    freeUploadSlots = 1;


	// REMOVE THIS BEFORE COMMITING TO SVN
	apiKey = "ZDdkZmVlODdhOWQxNzEwMTU3Y2I4YmU3NTFiZjcwNjExOTQyNjM1";
	ifileServerComms = new IfileServerComms(apiKey);

	ui.uploadTable->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
	uploadTableHeaders << "File Name" << "Size" << "File Location" << "Attach To Folder";

	ui.fileTable->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
	fileTableHeaders << "G" << "Name" << "Share" << "Size" << "Upload" << "# Downloads" << "Copy";

	ui.folderTable->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
	folderTableHeaders << "Name" << "Share" << "Visibility" << "Created" << "# Files" << "Folder Action";

	connect(ui.addFileBtn, SIGNAL(clicked()), this, SLOT(addUploadFile()));
	connect(ui.addFileAction, SIGNAL(triggered(bool)), this, SLOT(addUploadFile()));

	connect(ui.openFileListAction, SIGNAL(triggered(bool)), this, SLOT(addUploadFileList()));
	connect(ui.addFileListBtn, SIGNAL(clicked()), this, SLOT(addUploadFileList()));

	connect(ui.addFolderAction, SIGNAL(triggered(bool)), this, SLOT(addUploadFolder()));
	connect(ui.addFolderBtn, SIGNAL(clicked()), this, SLOT(addUploadFolder()));

	connect(ui.startUploadAction, SIGNAL(triggered(bool)), this, SLOT(startUpLoad()));
	connect(ui.startUploadBtn, SIGNAL(clicked()), this, SLOT(startUpLoad()));

	connect(ui.stopUploadBtn, SIGNAL(clicked()), this, SLOT(stopUpLoad()));
	connect(ui.stopUploadAction, SIGNAL(triggered(bool)), this, SLOT(stopUpLoad()));

	connect(ui.enterAccountKeyAction, SIGNAL(triggered(bool)), this, SLOT(enterAccountKey()));
	//connect(ui.addFolderToAccountAction, SIGNAL(triggered(bool)), this, SLOT(addFolder()));
	//connect(ui.searchAction, SIGNAL(triggered(bool)), this, SLOT(searchAccount()));
	connect(ui.accountInfoAction, SIGNAL(triggered(bool)), this, SLOT(getAccountStats()));
	connect(ui.aboutAction, SIGNAL(triggered(bool)), this, SLOT(aboutApp()));
	connect(ui.settingsAction, SIGNAL(triggered(bool)), this, SLOT(appSettings()));
	connect(ui.helpAction, SIGNAL(triggered(bool)), this, SLOT(appHelp()));

	connect(ui.mainTabWidget, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int)));

	//connect(ifileServerComms, SIGNAL(fileStatusFinished(IfileServerComms::FileStatusResponse)),
                //this, SLOT(fileStatus(IfileServerComms::FileStatusResponse)));

	connect(ifileServerComms, SIGNAL(listFoldersFinished(QList<IfileServerComms::FolderDetails>)),
	            this, SLOT(folderListReceived(QList<IfileServerComms::FolderDetails>)));

	connect(ifileServerComms, SIGNAL(listFilesFinished(QList<IfileServerComms::FileDetails>)),
                this, SLOT(fileListReceived(QList<IfileServerComms::FileDetails>)));

	connect(ifileServerComms, SIGNAL(accountStatsFinished(IfileServerComms::AccountStatsResponse)),
                this, SLOT(accountStatsUpdate(IfileServerComms::AccountStatsResponse)));

	connect(ui.exitAction, SIGNAL(triggered()), this, SLOT(exit()));
}

//----------------------------------------------------------------------------------------

ifileApp::~ifileApp()
{
    if (folderTableItemOne)
    {
        delete folderTableItemOne;
        folderTableItemOne = NULL;
    }

    if (folderTableItemTwo)
    {
        delete folderTableItemTwo;
        folderTableItemTwo = NULL;
    }

    if (folderTableItemThree)
    {
        delete folderTableItemThree;
        folderTableItemThree = NULL;
    }

    if (folderTableItemFour)
    {
        delete folderTableItemFour;
        folderTableItemFour = NULL;
    }

    if (folderTableItemFive)
    {
        delete folderTableItemFive;
        folderTableItemFive = NULL;
    }

    if (folderTableItemSix)
    {
        delete folderTableItemSix;
        fileTableItemSix = NULL;
    }

    if (fileTableItemTwo)
    {
        delete fileTableItemTwo;
        fileTableItemTwo = NULL;
    }

    if (fileTableItemThree)
    {
        delete fileTableItemThree;
        fileTableItemThree = NULL;
    }

    if (fileTableItemFour)
    {
        delete fileTableItemFour;
        fileTableItemFour = NULL;
    }

    if (fileTableItemFive)
    {
        delete fileTableItemFive;
        fileTableItemFive = NULL;
    }

    if (fileTableItemSix)
    {
        delete fileTableItemSix;
        fileTableItemSix = NULL;
    }

    if (fileTableItemSeven)
    {
        delete fileTableItemSeven;
        fileTableItemSeven = NULL;
    }

    if (uploadProcess)
    {
        delete uploadProcess;
        uploadProcess = NULL;
    }

    if (uploadTableItemOne)
    {
        delete uploadTableItemOne;
        uploadTableItemOne = NULL;
    }

    if (uploadTableItemTwo)
    {
        delete uploadTableItemTwo;
        uploadTableItemTwo = NULL;
    }

    if (uploadTableItemThree)
    {
        delete uploadTableItemThree;
        uploadTableItemThree = NULL;
    }

    if (uploadTableItemFour)
    {
        delete uploadTableItemFour;
        uploadTableItemFour = NULL;
    }

    if (accountFolders)
    {
        delete accountFolders;
        accountFolders = NULL;
    }

    if (signalMapper)
    {
        delete signalMapper;
        signalMapper = NULL;
    }

    if (groupCheckBox)
    {
        delete groupCheckBox;
        groupCheckBox = NULL;
    }

    if (ifileServerComms)
    {
        delete ifileServerComms;
        ifileServerComms = NULL;
    }
}

//----------------------------------------------------------------------------------------

void ifileApp::startUpLoad()
{
    uploadLock.lock();

    ui.startUploadBtn->setEnabled(false);
    ui.startUploadAction->setEnabled(false);

    if (uploadFiles.size() && keepProcessing && freeUploadSlots)
    {
        if (uploadFiles.size() == 1)
        {
            qDebug() << "last";
            uploadProcess = new UploadProcess(apiKey, uploadFiles.at(0), true);
        }
        else
        {
            qDebug() << "not last";
            uploadProcess = new UploadProcess(apiKey, uploadFiles.at(0), false);
        }

        connect(uploadProcess, SIGNAL(uploadProgress(int, qint64)), ui.uploadProgressBar, SLOT(setValue(int)));

        connect(uploadProcess, SIGNAL(uploadFinished()), this, SLOT(currentUploadFinished()));
        connect(uploadProcess, SIGNAL(lastUploadFinished()), this, SLOT(allUploadsFinsihed()));

        uploadProcess->start();
        uploadFiles.removeAt(0);
        ui.uploadTable->removeRow(0);
        freeUploadSlots--;
    }

    uploadLock.unlock();
}

//----------------------------------------------------------------------------------------

void ifileApp::currentUploadFinished()
{
    qDebug() << "current";
    uploadFinishedLock.lock();

    freeUploadSlots++;
    startUpLoad();

    uploadFinishedLock.unlock();
}

//----------------------------------------------------------------------------------------

void ifileApp::allUploadsFinsihed()
{
    qDebug() << "all";
    ui.startUploadBtn->setEnabled(true);
    ui.startUploadAction->setEnabled(true);
    freeUploadSlots++;
    keepProcessing = false;
}

//----------------------------------------------------------------------------------------

void ifileApp::stopUpLoad()
{
    //ui.uploadTable->removeRow();
}

//----------------------------------------------------------------------------------------

void ifileApp::addUploadFile()
{
    // Get the list of folders from the account
    ifileServerComms->listFolders();

    QFileDialog dialog(this);
    dialog.setFileMode(QFileDialog::ExistingFiles);

    signalMapper = new QSignalMapper(this);

    if (dialog.exec())
    {
        uploadFiles.append(dialog.selectedFiles());

        ui.uploadTable->clear();
        ui.uploadTable->setHorizontalHeaderLabels(uploadTableHeaders);

        // Create upload table items for each file
        for (int row = 0; row < uploadFiles.size(); row++)
        {
            if (QFile::exists(uploadFiles.at(row)))
            {
                QFile file (uploadFiles.at(row));
                QFileInfo fileInfo(file);
                int rows = ui.uploadTable->rowCount();
                ui.uploadTable->insertRow(rows);

                // File name
                uploadTableItemOne = new QTableWidgetItem(fileInfo.fileName());
                uploadTableItemOne->setFlags(Qt::ItemIsEnabled);
                ui.uploadTable->setItem(rows, 0, uploadTableItemOne);

                uploadTableItemTwo = new QTableWidgetItem(tr("%1 KB")
                                        .arg(int((fileInfo.size() + 1023) / 1024)));
                uploadTableItemTwo->setFlags(Qt::ItemIsEnabled);
                ui.uploadTable->setItem(rows, 1, uploadTableItemTwo);

                uploadTableItemThree = new QTableWidgetItem(fileInfo.absoluteFilePath());
                uploadTableItemThree->setFlags(Qt::ItemIsEnabled);
                ui.uploadTable->setItem(rows, 2, uploadTableItemThree);

                accountFolders = new QComboBox(this);
                accountFolders->addItems(foldList);
                ui.uploadTable->setCellWidget(rows, 3, accountFolders);

                // Maps the combobox accountFolders signal
                connect(accountFolders, SIGNAL(currentIndexChanged(int)), signalMapper, SLOT(map()));
                signalMapper->setMapping(accountFolders, QString("%1").arg(rows));
            }

        }

        connect(signalMapper, SIGNAL(mapped(const QString &)), this, SLOT(tableItemChanged(const QString &)));
    }
}

//----------------------------------------------------------------------------------------

void ifileApp::addUploadFileList()
{
    QFileDialog dialog(this);
    dialog.setFileMode(QFileDialog::AnyFile);

    QString fileList;
    if (dialog.exec())
    {
        fileList = dialog.selectedFiles().at(0);

        // process file list and add each entry to uploadFileList
    }
}

//----------------------------------------------------------------------------------------

void ifileApp::addUploadFolder()
{
    QFileDialog dialog(this);
    dialog.setFileMode(QFileDialog::DirectoryOnly);

    if (dialog.exec())
    {
        uploadFolders = dialog.selectedFiles();
    }
}

//----------------------------------------------------------------------------------------

void ifileApp::fileStatus(IfileServerComms::FileStatusResponse fileStatusResponse)
{
    qDebug() << "blah" << fileStatusResponse.fileKey;
}

//----------------------------------------------------------------------------------------

void ifileApp::exit()
{
        qApp->quit();
}

//----------------------------------------------------------------------------------------

void ifileApp::tabChanged(int tabIndex)
{
    if (ui.mainTabWidget->tabText(tabIndex).contains("Browse"))
    {
        // get list of file and add to table
        ifileServerComms->listFiles(1, "ts_uploaded", "desc");

        // get list of folders and add to table.
        ifileServerComms->listFolders();
    }
}

//----------------------------------------------------------------------------------------

void ifileApp::folderListReceived(QList<IfileServerComms::FolderDetails> folderDetailList)
{
    ui.folderTable->clear();
    ui.folderTable->setRowCount(0);
    ui.folderTable->setHorizontalHeaderLabels(folderTableHeaders);

    foldList.clear();
    folderKeyMap.clear();

    foldList.append("");

    // Create upload table items for each file
    for (int row = 0; row < folderDetailList.size(); row++)
    {
        int rows = ui.folderTable->rowCount();
        ui.folderTable->insertRow(rows);
        foldList.append(folderDetailList.at(row).folderName);

        folderKeyMap[folderDetailList.at(row).folderName] = folderDetailList.at(row).folderKey;

        // Folder name
        folderTableItemOne = new QTableWidgetItem(folderDetailList.at(row).folderName);
        folderTableItemOne->setFlags(Qt::ItemIsEnabled);
        ui.folderTable->setItem(rows, 0, folderTableItemOne);

        // Share options
        folderTableItemTwo = new QTableWidgetItem("S");
        folderTableItemTwo->setFlags(Qt::ItemIsEnabled);
        ui.folderTable->setItem(row, 1, folderTableItemTwo);

        // Folder privacy setting
        QString visibility = "Private";
        if (folderDetailList.at(row).folderType)
        {
            visibility = "Public";
        }

        folderTableItemThree = new QTableWidgetItem(visibility);
        folderTableItemThree->setFlags(Qt::ItemIsEnabled);
        ui.folderTable->setItem(rows, 2, folderTableItemThree);

        // Folder created date not implemented in API ???
        folderTableItemFour = new QTableWidgetItem("-- -- --");
        folderTableItemFour->setFlags(Qt::ItemIsEnabled);
        ui.folderTable->setItem(row, 3, folderTableItemFour);

        // Number of files in the folder
        folderTableItemFive = new QTableWidgetItem(QString("%1").arg(folderDetailList.at(row).numberOfFiles));
        folderTableItemFive->setFlags(Qt::ItemIsEnabled);
        ui.folderTable->setItem(rows, 4, folderTableItemFive);

        // Folder actions not implemented in ifile API ???
        folderTableItemSix = new QTableWidgetItem("A");
        folderTableItemSix->setFlags(Qt::ItemIsEnabled);
        ui.folderTable->setItem(row, 5, folderTableItemSix);
    }
}

//----------------------------------------------------------------------------------------

void ifileApp::fileListReceived(QList<IfileServerComms::FileDetails> fileDetailList)
{
    ui.fileTable->clear();
    ui.fileTable->setRowCount(0);
    ui.fileTable->setHorizontalHeaderLabels(fileTableHeaders);

    // Create upload table items for each file
    for (int row = 0; row < fileDetailList.size(); row++)
    {
        int rows = ui.fileTable->rowCount();
        ui.fileTable->insertRow(rows);

        // G - will change to check box later for Grouping
        groupCheckBox = new QCheckBox(this);
        ui.fileTable->setCellWidget(rows, 0, groupCheckBox);

        // File Name
        fileTableItemTwo = new QTableWidgetItem(fileDetailList.at(row).fileName);
        fileTableItemTwo->setFlags(Qt::ItemIsEnabled);
        ui.fileTable->setItem(rows, 1, fileTableItemTwo);

        // Share options
        fileTableItemThree = new QTableWidgetItem("S");
        fileTableItemThree->setFlags(Qt::ItemIsEnabled);
        ui.fileTable->setItem(row, 2, fileTableItemThree);

        // File Size
        fileTableItemFour = new QTableWidgetItem(QString("%1 KB")
                .arg(int((fileDetailList.at(row).fileSize + 1023) / 1024)));
        fileTableItemFour->setFlags(Qt::ItemIsEnabled);
        ui.fileTable->setItem(rows, 3, fileTableItemFour);

        // File Uploaded date
        fileTableItemFive = new QTableWidgetItem("-- -- --");
        fileTableItemFive->setFlags(Qt::ItemIsEnabled);
        ui.fileTable->setItem(row, 4, fileTableItemFive);

        // Number of Downloads
        fileTableItemSix = new QTableWidgetItem("??");
        fileTableItemSix->setFlags(Qt::ItemIsEnabled);
        ui.fileTable->setItem(rows, 5, fileTableItemSix);

        // Copy file share link to the clip board
        fileTableItemSeven = new QTableWidgetItem("??");
        fileTableItemSeven->setFlags(Qt::ItemIsEnabled);
        ui.fileTable->setItem(row, 6, fileTableItemSeven);
    }

}

//----------------------------------------------------------------------------------------

void ifileApp::setApiKey(QString _apiKey)
{
    apiKey = _apiKey;
}

//----------------------------------------------------------------------------------------

void ifileApp::setMaxUploadSlots(int slots)
{
    //maxUploadSlots = slots;
}

//----------------------------------------------------------------------------------------

void ifileApp::tableItemChanged(const QString row)
{
    bool ok;
    QComboBox * combo = (QComboBox *) ui.uploadTable->cellWidget(row.toInt(&ok, 10), 3);
    QString fileLoc = ui.uploadTable->item(row.toInt(&ok, 10), 2)->text();

    uploadFolderKeyMap[fileLoc] = folderKeyMap[combo->currentText()];

    //qDebug() << "Current text " << combo->currentText();
    //qDebug() << "MAP " << uploadFolderKeyMap[fileLoc];
}

//----------------------------------------------------------------------------------------

void ifileApp::getAccountStats()
{
    ifileServerComms->getAccountStats();
}

//----------------------------------------------------------------------------------------

void ifileApp::accountStatsUpdate(IfileServerComms::AccountStatsResponse accountStatsResponse)
{
    QMessageBox::information(this, tr("Account Stats"),
                QString("Account storage: %1 KB.\n Bandwidth used: %2 Kb.\n Total number of files: %3.\n")
                .arg(int((accountStatsResponse.storgaeUsed + 1023) / 1024))
                .arg(int((accountStatsResponse.bandwidthUsed + 1023) / 1024))
                .arg(accountStatsResponse.numberOfFiles),
                                    QMessageBox::Ok);
}

//----------------------------------------------------------------------------------------

void ifileApp::appHelp()
{
    QMessageBox::information(this, tr("Help!"),
                QString("Just follow your nose!"), QMessageBox::Ok);
}

//----------------------------------------------------------------------------------------

void ifileApp::aboutApp()
{
    QMessageBox::information(this, tr("About this app"), QString("Ifile uploader and account maintence!"), QMessageBox::Ok);
}
